array: Add null-termination
authorBenjamin Otte <otte@redhat.com>
Thu, 2 Jul 2020 21:32:04 +0000 (23:32 +0200)
committerBenjamin Otte <otte@redhat.com>
Thu, 16 Jul 2020 16:09:57 +0000 (18:09 +0200)
gdk/gdkarrayimpl.c
testsuite/gdk/array.c
testsuite/gdk/arrayimpl.c

index 238dd5d2b88b7fafe2eeeae50404a6ad9bf13f70..37c722f099b3369a36e9001934738259d0e055e3 100644 (file)
@@ -39,6 +39,12 @@ G_BEGIN_DECLS
 #endif
 #endif
 
+#ifdef GDK_ARRAY_NULL_TERMINATED
+#define GDK_ARRAY_REAL_SIZE(_size) ((_size) + 1)
+#else
+#define GDK_ARRAY_REAL_SIZE(_size) (_size)
+#endif
+
 /* make this readable */
 #define _T_ GDK_ARRAY_ELEMENT_TYPE
 #define GdkArray GDK_ARRAY_TYPE_NAME
@@ -54,7 +60,7 @@ struct GdkArray
   _T_ *end;
   _T_ *end_allocation;
 #ifdef GDK_ARRAY_PREALLOC
-  _T_ preallocated[GDK_ARRAY_PREALLOC];
+  _T_ preallocated[GDK_ARRAY_REAL_SIZE(GDK_ARRAY_PREALLOC)];
 #endif
 };
 
@@ -66,6 +72,9 @@ gdk_array(init) (GdkArray *self)
   self->start = self->preallocated;
   self->end = self->start;
   self->end_allocation = self->start + GDK_ARRAY_PREALLOC;
+#ifdef GDK_ARRAY_NULL_TERMINATED
+  *self->start = *(_T_[1]) {};
+#endif
 #else
   self->start = NULL;
   self->end = NULL;
@@ -138,13 +147,21 @@ gdk_array(reserve) (GdkArray *self,
     return;
 
   size = gdk_array(get_size) (self);
-  new_size = 1 << g_bit_storage (MAX (n, 16) - 1);
+  new_size = 1 << g_bit_storage (MAX (GDK_ARRAY_REAL_SIZE (n), 16) - 1);
 
 #ifdef GDK_ARRAY_PREALLOC
   if (self->start == self->preallocated)
     {
       self->start = g_new (_T_, new_size);
-      memcpy (self->start, self->preallocated, sizeof (_T_) * size);
+      memcpy (self->start, self->preallocated, sizeof (_T_) * GDK_ARRAY_REAL_SIZE (size));
+    }
+  else
+#endif
+#ifdef GDK_ARRAY_NULL_TERMINATED
+  if (self->start == NULL)
+    {
+      self->start = g_new (_T_, new_size);
+      *self->start = *(_T_[1]) {};
     }
   else
 #endif
@@ -152,6 +169,9 @@ gdk_array(reserve) (GdkArray *self,
 
   self->end = self->start + size;
   self->end_allocation = self->start + new_size;
+#ifdef GDK_ARRAY_NULL_TERMINATED
+  self->end_allocation--;
+#endif
 }
 
 G_GNUC_UNUSED static void
@@ -161,19 +181,22 @@ gdk_array(splice) (GdkArray *self,
                    _T_       *additions,
                    gsize      added)
 {
-  gssize size = gdk_array(get_size) (self);
+  gsize size;
+  gsize remaining;
 
+  size = gdk_array(get_size) (self);
   g_assert (pos + removed <= size);
+  remaining = size - pos - removed;
 
   gdk_array(free_elements) (gdk_array(index) (self, pos),
                             gdk_array(index) (self, pos + removed));
 
   gdk_array(reserve) (self, size - removed + added);
 
-  if (pos + removed < size && removed != added)
+  if (GDK_ARRAY_REAL_SIZE (remaining) && removed != added)
     memmove (gdk_array(index) (self, pos + added),
              gdk_array(index) (self, pos + removed),
-             (size - pos - removed) * sizeof (_T_));
+             GDK_ARRAY_REAL_SIZE (remaining) * sizeof (_T_));
 
   if (added)
     memcpy (gdk_array(index) (self, pos),
@@ -210,10 +233,12 @@ gdk_array(get) (GdkArray *self,
 #undef gdk_array_paste_more
 #undef gdk_array_paste
 #undef gdk_array
+#undef GDK_ARRAY_REAL_SIZE
 
-#undef GDK_ARRAY_PREALLOC
 #undef GDK_ARRAY_ELEMENT_TYPE
 #undef GDK_ARRAY_NAME
 #undef GDK_ARRAY_TYPE_NAME
+#undef GDK_ARRAY_PREALLOC
+#undef GDK_ARRAY_NULL_TERMINATED
 
 #endif
index d513b31a82d6a84457c43409a7c7668f65ef7906..f9d5677b2c0893cb0bc0457c754c2579638b864e 100644 (file)
@@ -50,6 +50,34 @@ int_free_func (int data)
 #define GDK_ARRAY_FREE_FUNC int_free_func
 #include "arrayimpl.c"
 
+#define GDK_ARRAY_ELEMENT_TYPE int
+#define GDK_ARRAY_NAME null_int_array
+#define GDK_ARRAY_TYPE_NAME NullIntVector
+#define GDK_ARRAY_NULL_TERMINATED 1
+#include "arrayimpl.c"
+
+#define GDK_ARRAY_ELEMENT_TYPE int
+#define GDK_ARRAY_NAME null_pre_int_array
+#define GDK_ARRAY_TYPE_NAME NullPreIntVector
+#define GDK_ARRAY_PREALLOC 100
+#define GDK_ARRAY_NULL_TERMINATED 1
+#include "arrayimpl.c"
+
+#define GDK_ARRAY_ELEMENT_TYPE int
+#define GDK_ARRAY_NAME null_free_int_array
+#define GDK_ARRAY_TYPE_NAME NullFreeIntVector
+#define GDK_ARRAY_FREE_FUNC int_free_func
+#define GDK_ARRAY_NULL_TERMINATED 1
+#include "arrayimpl.c"
+
+#define GDK_ARRAY_ELEMENT_TYPE int
+#define GDK_ARRAY_NAME null_pre_free_int_array
+#define GDK_ARRAY_TYPE_NAME NullPreFreeIntVector
+#define GDK_ARRAY_PREALLOC 100
+#define GDK_ARRAY_FREE_FUNC int_free_func
+#define GDK_ARRAY_NULL_TERMINATED 1
+#include "arrayimpl.c"
+
 int
 main (int argc, char *argv[])
 {
@@ -59,11 +87,19 @@ main (int argc, char *argv[])
   g_test_add_func ("/intarray/simple", int_array_test_simple);
   g_test_add_func ("/intarray/prealloc/simple", pre_int_array_test_simple);
   g_test_add_func ("/intarray/freefunc/simple", free_int_array_test_simple);
-  g_test_add_func ("/intarray/prealloc_freefunc_simple", pre_free_int_array_test_simple);
+  g_test_add_func ("/intarray/prealloc/freefunc/simple", pre_free_int_array_test_simple);
+  g_test_add_func ("/intarray/null/simple", null_int_array_test_simple);
+  g_test_add_func ("/intarray/null/prealloc/simple", null_pre_int_array_test_simple);
+  g_test_add_func ("/intarray/null/freefunc/simple", null_free_int_array_test_simple);
+  g_test_add_func ("/intarray/null/prealloc/freefunc/simple", null_pre_free_int_array_test_simple);
   g_test_add_func ("/intarray/splice", int_array_test_splice);
   g_test_add_func ("/intarray/prealloc/splice", pre_int_array_test_splice);
   g_test_add_func ("/intarray/freefunc/splice", free_int_array_test_splice);
-  g_test_add_func ("/intarray/prealloc_freefunc_splice", pre_free_int_array_test_splice);
+  g_test_add_func ("/intarray/prealloc/freefunc/splice", pre_free_int_array_test_splice);
+  g_test_add_func ("/intarray/null/splice", null_int_array_test_splice);
+  g_test_add_func ("/intarray/null/prealloc/splice", null_pre_int_array_test_splice);
+  g_test_add_func ("/intarray/null/freefunc/splice", null_free_int_array_test_splice);
+  g_test_add_func ("/intarray/null/prealloc/freefunc/splice", null_pre_free_int_array_test_splice);
 
   return g_test_run ();
 }
index f9320cb113a7c7d22cdee3995d40b1034b7d2b5c..286f64d6783c711f0064609b6e8e9440d695f37e 100644 (file)
@@ -36,6 +36,9 @@ gdk_array(test_simple) (void)
       g_assert_cmpint (gdk_array(get_size) (&v), ==, i);
       g_assert_cmpint (gdk_array(get_size) (&v), <=, gdk_array(get_capacity) (&v));
       gdk_array(append) (&v, i);
+#ifdef GDK_ARRAY_NULL_TERMINATED
+      g_assert_cmpint (*gdk_array(index) (&v, gdk_array(get_size) (&v)), ==, 0);
+#endif
     }
   g_assert_cmpint (gdk_array(get_size) (&v), ==, i);
   g_assert_cmpint (gdk_array(get_size) (&v), <=, gdk_array(get_capacity) (&v));
@@ -84,6 +87,10 @@ gdk_array(test_splice) (void)
 
       g_assert_cmpint (gdk_array(get_size) (&v), ==, old_size + add - remove);
       g_assert_cmpint (gdk_array(get_size) (&v), <=, gdk_array(get_capacity) (&v));
+#ifdef GDK_ARRAY_NULL_TERMINATED
+      if (gdk_array(get_size) (&v))
+        g_assert_cmpint (*gdk_array(index) (&v, gdk_array(get_size) (&v)), ==, 0);
+#endif
       for (j = 0; j < add; j++)
         g_assert_cmpint (gdk_array(get) (&v, pos + j), ==, additions[j]);
     }
@@ -100,9 +107,11 @@ gdk_array(test_splice) (void)
 #undef gdk_array_paste_more
 #undef gdk_array_paste
 #undef gdk_array
+#undef GDK_ARRAY_REAL_SIZE
 
-#undef GDK_ARRAY_PREALLOC
 #undef GDK_ARRAY_ELEMENT_TYPE
 #undef GDK_ARRAY_NAME
 #undef GDK_ARRAY_TYPE_NAME
+#undef GDK_ARRAY_PREALLOC
+#undef GDK_ARRAY_NULL_TERMINATED